#include "JetsonEnc.h"
#include <opencv2/opencv.hpp>
#include <fstream>
#include <iostream>
#include <unistd.h>
#include <cstring>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/stat.h> // POSIX
#include <sys/types.h> // POSIX
#include <errno.h> 
#include <cstdlib>  // 用于 system()
#include <cstdio>   // 用于 std::remove
#include <thread>

#ifdef _WIN32
#include <direct.h> // Windows
inline  int createDirectory(const char* path) {
    return _mkdir(path);
}
#else
// 取消任何可能的宏定义冲突
#ifdef mkdir
#undef mkdir
#endif
inline int createDirectory(const char* path) {
    return mkdir(path, 0755); // 使用0755作为权限
}
#endif


const char *target_ip = "192.168.137.1"; // 目标 IP 地址
const int target_port = 8554;           // 目标端口

int udp_socket;
struct sockaddr_in dest_addr;

std::ofstream left_output_file;
std::ofstream right_output_file;

class EncLDataWriter : public JetsonEncListner {
public:
    void OnJetsonEncData(unsigned char *data, int data_len) override {
        if (data == nullptr || data_len <= 0) {
            std::cerr << "Received invalid data from encoder." << std::endl;
            return;
        }
        left_output_file.write(reinterpret_cast<char *>(data), data_len);
    }
};

class EncRDataWriter : public JetsonEncListner {
public:
    void OnJetsonEncData(unsigned char *data, int data_len) override {
        if (data == nullptr || data_len <= 0) {
            std::cerr << "Received invalid data from encoder." << std::endl;
            return;
        }
        right_output_file.write(reinterpret_cast<char *>(data), data_len);
    }
};

bool folderExists(const std::string& folderName) {
    struct stat info;
    if (stat(folderName.c_str(), &info) != 0) {
        return false; // 文件夹不存在
    } else if (info.st_mode & S_IFDIR) {
        return true; // 文件夹存在
    }
    return false; // 不是文件夹
}


std::string createNextFolder(const std::string& baseName) {
    int folderIndex = 1;
    std::string newFolderName;

    // 找到第一个不存在的文件夹名
    while (true) {
        newFolderName = baseName + std::to_string(folderIndex);
        if (!folderExists(newFolderName)) {
            break;
        }
        folderIndex++;
    }
    // 创建文件夹
    if (createDirectory(newFolderName.c_str()) == 0) {
        std::cout << "Created folder: " << newFolderName << std::endl;
        return newFolderName;
    } else {
        std::cerr << "Failed to create folder: " << newFolderName << std::endl;
        return "";
    }
}

int run_command(const std::string &command) {
    int result = system(command.c_str());
    if (result != 0) {
        std::cerr << "Command failed: " << command << std::endl;
    } else {
        std::cout << "Command succeeded: " << command << std::endl;
    }
    return result;  // 返回命令执行的结果
}

int main(int argc, char **argv) {

    cv::VideoCapture cap(0);
    if (!cap.isOpened()) {
        std::cerr << "无法打开摄像头" << std::endl;
        return -1;
    }
    std::string baseName = "/home/ubuntu/saveVideo/zhuitao";
    std::string createdFolder = createNextFolder(baseName);
    left_output_file.open(createdFolder + "/left_video.h264", std::ios::binary | std::ios::app);
    if (!left_output_file.is_open()) {
        std::cerr << "Error opening the output file." << std::endl;
        return -1;
    }
    right_output_file.open(createdFolder + "/right_video.h264", std::ios::binary | std::ios::app);
    if (!right_output_file.is_open()) {
        std::cerr << "Error opening the output file." << std::endl;
        return -1;
    }

    int width = cap.get(cv::CAP_PROP_FRAME_WIDTH) / 2;
    int height = cap.get(cv::CAP_PROP_FRAME_HEIGHT);
    // int frame_width = static_cast<int>(cap.get(cv::CAP_PROP_FRAME_WIDTH)) / 2;
    // int frame_height = static_cast<int>(cap.get(cv::CAP_PROP_FRAME_HEIGHT));
    // int fps = static_cast<int>(cap.get(cv::CAP_PROP_FPS));
    // cv::VideoWriter video_writer(createdFolder + "/video.avi", cv::VideoWriter::fourcc('M', 'J', 'P', 'G'), fps,
    //                              cv::Size(frame_width, frame_height));
    // // 检查 VideoWriter 是否成功打开
    // if (!video_writer.isOpened()) {
    //     std::cout << "无法打开输出视频文件进行写入！" << std::endl;
    //     return -1;
    // }
    std::cout << "Width: " << width << ", Height: " << height << std::endl;

    // 初始化左目编码器
    JetsonEnc *left_encoder = new JetsonEnc(width, height);
    EncLDataWriter *left_writer = new EncLDataWriter();
    left_encoder->SetDecCallBack(static_cast<JetsonEncListner *>(left_writer));

    // 初始化右目编码器
    JetsonEnc *right_encoder = new JetsonEnc(width, height);
    EncRDataWriter *right_writer = new EncRDataWriter();
    right_encoder->SetDecCallBack(static_cast<JetsonEncListner *>(right_writer));

    cv::Mat frame, lframe, rframe;
    size_t frame_size = width * height * 3 / 2;
    int cnt = 0;

    while (true) {  // cnt < 1000
        char *left_buffer = new char[frame_size];
        char *right_buffer = new char[frame_size];

        cap >> frame;
        if (frame.empty()) {
            std::cerr << "Captured empty frame!" << std::endl;
            break;
        }
        lframe = frame(cv::Rect(0, 0, width, height));
        rframe = frame(cv::Rect(width, 0, width, height));
        // video_writer.write(lframe);


        cv::cvtColor(lframe, lframe, cv::COLOR_BGR2YUV_I420); 
        cv::cvtColor(rframe, rframe, cv::COLOR_BGR2YUV_I420); 
        std::memcpy(left_buffer, lframe.data, frame_size);
        std::memcpy(right_buffer, rframe.data, frame_size);
        left_encoder->AddFrame(left_buffer, frame_size);
        right_encoder->AddFrame(right_buffer, frame_size);
        // 显示当前帧（可选）
        cv::namedWindow("Frame", cv::WINDOW_NORMAL);
        cv::imshow("Frame", frame);
        if (cv::waitKey(1) == 'q') {
            break;
        }
        // usleep(1000 * 40); // 模拟帧率延迟
        cnt++;
        // delete[] buffer;
    }

    std::cout << "捕获结束" << std::endl;

    while (left_encoder->GetQueueSize() != 0) {
        usleep(1000 * 40);
    }
    while (right_encoder->GetQueueSize() != 0) {
        usleep(1000 * 40);
    }

    std::cout << "编码结束" << std::endl;
    std::string command1 = "ffmpeg -r 15 -i " + createdFolder + "/right_video.h264 -c:v libx264 -f mp4 " + createdFolder + "/right_video.mp4";
    std::string command2 = "ffmpeg -r 15 -i " + createdFolder + "/left_video.h264 -c:v libx264 -f mp4 "+ createdFolder + "/left_video.mp4";
    // 使用 system() 函数运行命令
    // 保存返回结果
    int result1, result2;

    // 使用多线程并行执行命令
    std::thread thread1([&]() { result1 = run_command(command1); });
    std::thread thread2([&]() { result2 = run_command(command2); });
    // 等待两个线程结束
    thread1.join();
    thread2.join();
    // 检查命令执行结果
    if (result1 == 0 && result2 == 0) {
        std::cout << "命令执行成功！" << std::endl;
        // 删除 right_video.h264 left_video.h264 文件
        if (std::remove((createdFolder + "/right_video.h264").c_str()) == 0 && std::remove((createdFolder + "/left_video.h264").c_str()) == 0) {
            std::cout << "两个文件删除成功！" << std::endl;
        } else {
            std::cerr << "无法删除原始文件！" << std::endl;
        }
    } else {
        std::cout << "命令执行失败，错误码：" << result1 << "\t" << result2 << std::endl;
    }

    // delete[] buffer;
    cv::destroyAllWindows();
    cap.release();
    // video_writer.release();
    delete left_encoder;
    delete right_encoder;
    delete left_writer;
    delete right_writer;
    left_output_file.close();
    right_output_file.close();
    return 0;
}
